﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Ruleweaver.Rules.CheckMethods
{
	[ContractClass(typeof(SingleTypeCheckMethodContract))]
	public abstract class SingleTypeCheckMethod : CheckMethod
	{
		protected override bool SupportsTargetType(Type targetType)
		{
			return TargetType.IsAssignableFrom(targetType);
		}

		protected override MethodInfo GetMethod(Type targetType, Type checkType)
		{
			return GetMethod(checkType);
		}

		protected sealed override IEnumerable<object> GetCheckArguments(Type targetType)
		{
			return GetCheckArguments();
		}

		protected virtual IEnumerable<object> GetCheckArguments()
		{
			Contract.Ensures(Contract.Result<IEnumerable<object>>() != null);

			return Enumerable.Empty<object>();
		}

		protected abstract Type TargetType { get; }

		protected abstract MethodInfo GetMethod(Type checkType);
	}

	[ContractClassFor(typeof(SingleTypeCheckMethod))]
	internal abstract class SingleTypeCheckMethodContract : SingleTypeCheckMethod
	{
		protected override Type TargetType
		{
			get
			{
				Contract.Ensures(Contract.Result<Type>() != null);

				return null;
			}
		}

		protected override MethodInfo GetMethod(Type checkType)
		{
			Contract.Requires(checkType != null);
			Contract.Ensures(Contract.Result<MethodInfo>() != null);

			return null;
		}
	}
}